'''
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Copyright (c) 2009 bryan p. conrad
bconrad2@gmail.com

Created on: 7/26/2009

Version: 0.1

@author: bryan
'''
#===============================================================================
# Imports
#===============================================================================
import JT

class XRayCamera(JT.vtk.vtkCamera):
    """
    This class is a derived from vtkCamera.  It extends the class by
    adding the ability to calibrate the camera using the perspective camera model
    and calibration data.
    """
    #import Calibration

    def __init__(self):
        """
        """
        # Initialize vtkMath class for doing calibration
        self._vtkMath = JT.vtk.vtkMath()
        # Initialize the JointTrack calibration class
        self.IntCal = JT.InternalCalibration()
        # Initialize the JointTrack calibration class
        self.ExtCal = JT.ExternalCalibration()
        # image size must be specified before the view angle can be computed
        self._ImageSize = None
        self.calType = 'external'

    def SetInternalCalibration(self,IntCal):
        """
        filename is the path to a valid JointTrack calibration file.  The file
        will be read and the calibration class will be setup to contain the calibration
        parameters.

        TODO: is it possible to calibrate directly from a dicom image? since it is aware of focal distance, scale and offset?
        """
        #self.IntCal.LoadCalFile(filename)
        self.Cal = IntCal
        self.calType = 'internal'
        if self.Cal.isValid == True:
            self.DoCalibration()
            
    
    def DoCalibration(self):
        """
        Once a valid calibration object is defined, use this method to apply
        the parameters to the camera.
        """
        if self.calType.lower() == 'internal':
            #self.SetPosition(self.IntCal._XOffset,self.IntCal._YOffset,self.IntCal._FocalDistance)
            self.SetPosition(0, 0, 0)
            self.SetViewUp(0, 1, 0)
            self.SetViewAngle(self.Cal._viewAngle)
            # wc_x and wc_y are normalized to [-1,1]
            #wc_x = self.Cal._XOffset / self.Cal._PixelScale / self.Cal._ImageSize[0] * 2   
            #wc_y = self.Cal._YOffset / self.Cal._PixelScale / self.Cal._ImageSize[1] * 2
            #self.SetFocalPoint(0,0, -abs(self.Cal._FocalDistance))
            #self.SetWindowCenter(-wc_x, -wc_y);
            self.SetFocalPoint(self.IntCal._XOffset,self.IntCal._YOffset, -abs(self.Cal._FocalDistance))
            self.SetClippingRange(10,5000)
        else:
            #print "Doing external calibration on cal type: %s" % self.calType
            self.SetPosition(self.Cal._pSource)
            self.SetFocalPoint(self.Cal._centerDetector)
            self.SetViewAngle(self.Cal._viewAngle)
            #print "Camera Position: %s " % self.Cal._pSource
            #print "Focal Point: %s" % self.Cal._centerDetector 
            # logging.debug("Calibration succesfully applied to camera")

    def SetExternalCalibration(self,ExtCal):
        """
        ExtCal is a JTCal object that contains the necessary calibration
        parameters.  The path to the calibration file has to be specified
        seperately (through the JTCal object).  The calibration is automatically
        applied, if it is valid, through the call of DoCalibration.

        TODO: This method should be merged with SetInternalCalibration method
        above, which is currently a very different format (old JT style calibration).
        """
        self.Cal = ExtCal

        if self.ExtCal.isValid():
            self.calType = 'external'
            self.DoCalibration()

    def ComputeObjectPosition(self,object_world_dim,object_projection_dim):
        """
        """
        # JointTrack only uses 1 dimension for scale
        scale = self.IntCal._PixelScale

        position_object = (self.GetPosition()[0],self.GetPosition()[1],
                           self.GetPosition()[2]-object_world_dim[2]/2-
                           (self.GetPosition()[2]*object_world_dim[1]/
                           object_projection_dim[1]*scale))

        return position_object
